package app

import (
	"fmt"
	"net/http"
	"runtime"
	"runtime/debug"
	"time"
)

// HandlerFunc 定义请求处理函数的类型
// 接收一个Context指针作为参数
type HandlerFunc func(*Context)

// App 应用程序核心结构体
// globalFilters: 全局中间件列表
// exceptionHandler: 异常处理函数
// routers: 路由集合
type App struct {
	globalFilters    []IFilter   //全局中间件
	exceptionHandler HandlerFunc //异常处理函数
	routers          []*Router   //路由集合
}

var (
	// WebApp 全局应用程序实例
	WebApp App
)

// init 初始化函数，在包被导入时自动执行
// 初始化WebApp实例，设置默认值
func init() {
	WebApp = App{globalFilters: make([]IFilter, 0, 0), exceptionHandler: nil, routers: make([]*Router, 0, 0)}
}

// 注册全局路由
// RegisterGlobalFilter 注册全局中间件
// filters: 可变参数，接收多个IFilter类型的中间件
func RegisterGlobalFilter(filters ...IFilter) {
	WebApp.globalFilters = append(WebApp.globalFilters, filters...)
}

// 注册异常处理函数
// RegisterExceptionHandler 注册异常处理函数
// handlerfunc: 异常处理函数
func RegisterExceptionHandler(handlerfunc HandlerFunc) {
	WebApp.exceptionHandler = handlerfunc
}

// 启动应用程序
// Run 启动应用程序
// addr: 可变参数，指定监听地址（默认为":8080"）
func (app App) Run(addr ...string) {
	// 注册所有路由
	for _, router := range app.routers {
		HandleFunc(router)
	}

	// 设置监听地址
	var address string
	if len(addr) > 0 {
		address = addr[0]
	} else {
		address = ":8080"
	}

	fmt.Println("Listen On localhost", address)
	err := http.ListenAndServe(address, nil) //设置监听的端口
	if err != nil {
		fmt.Println("ListenAndServe_Error: ", err)
	}
}

// 处理路由对象
// HandleFunc 处理路由对象
// router: 路由对象，包含路径、处理函数和中间件
func HandleFunc(router *Router) {
	// HandleFunc 是一个路由处理函数包装器
	// 参数:
	//   router *Router - 包含路由路径、处理函数和中间件的路由对象
	//
	// 功能说明:
	// 1. 将路由注册到http.HandleFunc
	// 2. 创建请求上下文
	// 3. 处理异常恢复
	// 4. 执行全局中间件和路由中间件
	// 5. 最终执行路由处理函数

	// http.HandleFunc 是标准库函数，用于注册路由处理函数
	// 第一个参数是路由路径，第二个参数是处理函数
	http.HandleFunc(router.path, func(response http.ResponseWriter, request *http.Request) {
		// 创建请求上下文对象
		// Context包含:
		// - ResponseWriter: 用于写入HTTP响应
		// - Request: HTTP请求对象
		// - StartTime: 请求开始时间，用于性能监控
		ctx := &Context{ResponseWriter: response, Request: request, StartTime: time.Now()}

		// 异常处理机制
		// 使用defer确保在函数退出时执行
		defer func() {
			// recover()只能在defer函数中调用，用于捕获当前协程中的panic。
			// 如果没有发生panic，recover()会返回nil；如果发生了panic，recover()会捕获panic的值并恢复程序的正常执行。
			if err := recover(); err != nil {
				// 根据panic的类型创建异常信息
				switch err.(type) {
				case runtime.Error:
					ctx.Exception = Exception{Message: err.(runtime.Error).Error(), Stack: string(debug.Stack())}
				case string:
					ctx.Exception = Exception{Message: err.(string), Stack: ""}
				default:
					ctx.Exception = Exception{Message: "其它异常", Stack: ""}
				}

				// 如果注册了异常处理函数，则调用它
				if WebApp.exceptionHandler != nil {
					WebApp.exceptionHandler(ctx)
				}
			}
		}()

		// 执行全局中间件
		// 全局中间件会对所有路由生效
		if len(WebApp.globalFilters) > 0 {
			for _, filter := range WebApp.globalFilters {
				if ctx.IsEnd { // 检查是否提前结束请求
					break
				}
				// 使用defer确保中间件的退出逻辑被执行
				defer filter.OnExist(ctx)
				// 执行中间件的入口逻辑
				filter.OnEntry(ctx)
			}
		}

		// 执行路由特定的中间件
		// 这些中间件只对当前路由生效
		for _, filter := range router.filters {
			if ctx.IsEnd { // 检查是否提前结束请求
				break
			}
			defer filter.OnExist(ctx)
			filter.OnEntry(ctx)
		}

		// 执行路由处理函数
		// 只有当前面的中间件没有结束请求时才会执行
		if !ctx.IsEnd {
			router.handler(ctx)
		}
	})

}
